/*
 * File: Artistry.java
 * Name: Diego A. Falciola
 * Section Leader: Sam King
 * ==========================================================
 * 
 * The idea behind this work is to reproduce a painting 
 * from the famous painter Piet Mondrian 
 * combining different elements that fulfills the 
 * requirements of this task.
 * 
 * Since there is a limitation of GObjects to be added
 * I did not complete the painting but some of the abstract
 * elements that Piet showed in his painting were reproduced in 
 * this work 	
 * 
 * This work required to think a way of drawing stuff 
 * without exceeding the limits imposed but the assignment. 
 * Patterns had to be found in order to avoid magic numbers
 * 
 * The painting can be found here: http://goo.gl/pKCz6
 *
 */

import java.awt.Color;
import java.awt.Font;

import acm.graphics.*;
import acm.program.*;

public class Artistry extends GraphicsProgram {
	
	private final static int LINE_WIDTH = 15;
	
	// Vertical Lines
	private final static int POSITION_VERTICAL_ONE = 18;
	private final static int POSITION_VERTICAL_TWO = 80;
	private final static int POSITION_VERTICAL_THREE = 560;
	private final static int POSITION_VERTICAL_FOUR = 680;
	private final static int POSITION_VERTICAL_FIVE = 770;
	
	// Horizontal Lines
	private final static int POSITION_HORIZONTAL_ONE = 23;
	private final static int POSITION_HORIZONTAL_TWO = 235;
	private final static int POSITION_HORIZONTAL_THREE = 360;
	private final static int POSITION_HORIZONTAL_FOUR = 490;
	
	// Triangle
	private final static int POSITION_TRIANGLE_BOTTOM_LEFT = 300;
	private final static Color TRIANGLE_COLOR = 
		new Color(0.342f,0.770f,0.290f);
	
	// Circle  
	private final static int CIRCLE_RADIUS_BIG = 135;
	private final static int CIRCLE_RADIUS_SMALL = 120;
	private final static int POSITION_CIRCLE_X = 
		((POSITION_VERTICAL_THREE +	POSITION_VERTICAL_FOUR) / 2)
		-  CIRCLE_RADIUS_BIG;
	
	private final static Color CIRCLE_COLOR = 
		new Color(0.754f,0.274f,0.223f);
	
	// Rectangle
	private final static Color RECTANGLE_COLOR = 
		new Color(0.805f,0.230f,0.758f);
	
	// Cross
	private final static int POSITION_CROSS_X = POSITION_TRIANGLE_BOTTOM_LEFT 
												- 20;
	
	// Signature
	private final static int POSITION_SIGNATURE_X = 
		(POSITION_VERTICAL_THREE+POSITION_TRIANGLE_BOTTOM_LEFT)/2 - 75;
	private final static int POSITION_SIGNATURE_Y =  20;
	private final static int SIGNATURE_FONT_SIZE = 15;
	
	// Inspired By 
	private final static int POSITION_INSPIREDBY_X = 
		POSITION_VERTICAL_TWO + 40;
	private final static int POSITION_INSPIREDBY_Y = 18;
	private final static int INSPIREDBY_FONT_SIZE = 15;
	
	// App config 
	public static final int APPLICATION_WIDTH = 800;
	public static final int APPLICATION_HEIGHT = 800;
	
	public void run() {
		initializeCanvas();
		
		drawVerticalLines();
		
		drawHorizontalLines();
		
		drawCircles();
		
		drawTriangles();
		
		drawRectangles();
		
		drawCross();
		
		drawInspiration();
		
		signIt();
	}
	
	/**
	 *  Sets up canvas 
	 */
	private void initializeCanvas(){
		setBackground(Color.LIGHT_GRAY);
	}
	
	/**
	 *  Draws five vertical lines using POSITION_VERTICAL constants
	 */
	private void drawVerticalLines(){
		GRect verticalLineOne = new GRect(	POSITION_VERTICAL_ONE, 
											0, 
											LINE_WIDTH, 
											getHeight());
		verticalLineOne.setFilled(true);
		add(verticalLineOne);
		
		GRect verticalLineTwo = new GRect(	POSITION_VERTICAL_TWO, 
											0, 
											LINE_WIDTH, 
											getHeight());
		verticalLineTwo.setFilled(true);
		add(verticalLineTwo);
		
		GRect verticalLineThree = new GRect(POSITION_VERTICAL_THREE, 
											0, 
											LINE_WIDTH, 
											getHeight());
		verticalLineThree.setFilled(true);
		add(verticalLineThree);
		
		GRect verticalLineFour = new GRect(	POSITION_VERTICAL_FOUR, 
											0, 
											LINE_WIDTH, 
											getHeight());
		
		verticalLineFour.setFilled(true);
		add(verticalLineFour);
		
		GRect verticalLineFive = 
			new GRect(POSITION_VERTICAL_FIVE, 
					  0, 
					  LINE_WIDTH, 
					  getHeight());
		
		verticalLineFive.setFilled(true);
		add(verticalLineFive);
	}
	
	/**
	 *  Draws four horizontal lines
	 */
	private void drawHorizontalLines(){
		GRect horizontalLineOne = new GRect(0, 
											POSITION_HORIZONTAL_ONE, 
											getWidth(), 
											LINE_WIDTH );
		horizontalLineOne.setFilled(true);
		add(horizontalLineOne);
		
		GRect horizontalLineTwo = new GRect(0, 
											POSITION_HORIZONTAL_TWO, 
											getWidth(), 
											LINE_WIDTH );
		horizontalLineTwo.setFilled(true);
		add(horizontalLineTwo);
		
		GRect horizontalLineThree = new GRect(	0, 
												POSITION_HORIZONTAL_THREE, 
												getWidth(), 
												LINE_WIDTH );
		horizontalLineThree.setFilled(true);
		add(horizontalLineThree);

		GRect horizontalLineFour = new GRect(	0, 
												POSITION_HORIZONTAL_FOUR, 
												getWidth(), 
												LINE_WIDTH );
		horizontalLineFour.setFilled(true);
		add(horizontalLineFour);
	}
	
	
	/**
	 * Draw two circles using relations between 
	 * vertical and horizontal lines 
	 */
	private void drawCircles(){		
		GOval bigCircle = new GOval(POSITION_CIRCLE_X,   
									POSITION_HORIZONTAL_TWO, 
									// diameter of the circle
									CIRCLE_RADIUS_BIG*2, 
									CIRCLE_RADIUS_BIG*2); 
		bigCircle.setFilled(true);
		add(bigCircle);
		
		// draw circle inside using LINE_WIDTH separation from bigger circle
		GOval smallCircle = new GOval(	POSITION_CIRCLE_X + LINE_WIDTH, 
										POSITION_HORIZONTAL_TWO + LINE_WIDTH,
										// diameter of the circle
										CIRCLE_RADIUS_SMALL*2, 
										CIRCLE_RADIUS_SMALL*2);
			
		smallCircle.setFillColor(CIRCLE_COLOR);
		smallCircle.setFilled(true);
		add(smallCircle);
	}
	
	/**
	 *  Draw two triangles using relations between 
	 *  vertical and horizontal lines
	 */
	private void drawTriangles(){
		GPolygon bigTriangle = new GPolygon();
		
		// bottom left vertex
		// with base on POSITION_HORIZONTAL_TWO line
		bigTriangle.addVertex(	POSITION_TRIANGLE_BOTTOM_LEFT, 
								POSITION_HORIZONTAL_TWO);
		
		// bottom right vertex
		// with base on POSITION_HORIZONTAL_TWO line
		bigTriangle.addVertex(	POSITION_VERTICAL_THREE, 
								POSITION_HORIZONTAL_TWO);
		
		// center of the other two points, 
		// below the POSITION_HORIZONTAL_ONE line
		bigTriangle.addVertex((	POSITION_VERTICAL_THREE
									+POSITION_TRIANGLE_BOTTOM_LEFT) / 2, 
								POSITION_HORIZONTAL_ONE);
		bigTriangle.setFilled(true);
		add(bigTriangle);
		
		
		// same as above, but using LINE_WIDTH separation 
		// from the other triangle
		GPolygon smallTriangle = new GPolygon();
		smallTriangle.addVertex(POSITION_TRIANGLE_BOTTOM_LEFT + LINE_WIDTH, 
								POSITION_HORIZONTAL_TWO);
		smallTriangle.addVertex(POSITION_VERTICAL_THREE - LINE_WIDTH, 
								POSITION_HORIZONTAL_TWO);
		smallTriangle
			.addVertex((POSITION_VERTICAL_THREE+POSITION_TRIANGLE_BOTTOM_LEFT)
							/ 2,
						POSITION_HORIZONTAL_ONE + (LINE_WIDTH * 2));  		
		
		smallTriangle.setFillColor(TRIANGLE_COLOR); 
		smallTriangle.setFilled(true);
		add(smallTriangle);
	}
	
	/**
	 *  Draw two rectangles using relations between 
	 *  vertical and horizontal lines, and with the triangles.
	 */
	private void drawRectangles(){
		
		// draw big triangle 
		// with sides in POSITION_VERTICAL_TWO,
		// POSITION_HORIZONTAL_TWO, POSITION_HORIZONTAL_FOUR
		// and fourth side calculated using 
		// the POSITION+TRIANGLE_BOTTOM_LEFT_POINT
		GRect bigRectangle = 
			new GRect(	POSITION_VERTICAL_TWO + LINE_WIDTH, 
			POSITION_HORIZONTAL_TWO + LINE_WIDTH,
			POSITION_TRIANGLE_BOTTOM_LEFT - POSITION_VERTICAL_TWO, 
			POSITION_HORIZONTAL_FOUR- POSITION_HORIZONTAL_TWO );
		bigRectangle.setFilled(true);
		add(bigRectangle);
		
		// small rectangle, same as above but using LINE_WIDTH
		// separation from bigTriangle
		GRect smallRectangle = 
			new GRect(	POSITION_VERTICAL_TWO + LINE_WIDTH, 
			POSITION_HORIZONTAL_TWO + LINE_WIDTH,
			POSITION_TRIANGLE_BOTTOM_LEFT - POSITION_VERTICAL_TWO - LINE_WIDTH, 
			POSITION_HORIZONTAL_FOUR- POSITION_HORIZONTAL_TWO - LINE_WIDTH);
		smallRectangle.setFillColor(RECTANGLE_COLOR);
		
		smallRectangle.setFilled(true);
		add(smallRectangle);
	}
	
	/**
	 *  Draw two crosses using relations between 
	 *  vertical and horizontal lines.
	 */
	private void drawCross(){
		GPolygon lineCrossOneSideOne = new GPolygon();
		lineCrossOneSideOne.addVertex(	POSITION_CROSS_X, 
										POSITION_HORIZONTAL_FOUR + LINE_WIDTH);
		lineCrossOneSideOne.addVertex(	POSITION_CROSS_X + LINE_WIDTH, 
										POSITION_HORIZONTAL_FOUR + LINE_WIDTH);
		lineCrossOneSideOne.addVertex(	POSITION_VERTICAL_THREE, 
										getHeight()-LINE_WIDTH);
		lineCrossOneSideOne.addVertex(	POSITION_VERTICAL_THREE, 
										getHeight());
		
		lineCrossOneSideOne.setFilled(true);
		add(lineCrossOneSideOne);
		
		GPolygon lineCrossOneSideTwo = new GPolygon();
		lineCrossOneSideTwo.addVertex(	POSITION_CROSS_X, 
										getHeight());
		lineCrossOneSideTwo.addVertex(	POSITION_CROSS_X + LINE_WIDTH, 
										getHeight());
		lineCrossOneSideTwo.addVertex(	POSITION_VERTICAL_THREE+LINE_WIDTH, 
										POSITION_HORIZONTAL_FOUR);
		lineCrossOneSideTwo.addVertex(	POSITION_VERTICAL_THREE, 
										POSITION_HORIZONTAL_FOUR);
		lineCrossOneSideTwo.setFilled(true);
		add(lineCrossOneSideTwo);		
	}
	
	/**
	 *  Draw inspired by note
	 */
	private void drawInspiration(){
		drawLabel(	"Inspired By: Piet Mondrian", 
					POSITION_INSPIREDBY_X, 
					POSITION_INSPIREDBY_Y, 
					"Arial", 
					INSPIREDBY_FONT_SIZE, 
					Font.BOLD);
	}
	
	/**
	 *  Sign the work
	 */
	private void signIt(){
		drawLabel(	"Artistry by Diego Falciola", 
					POSITION_SIGNATURE_X, 
					getHeight()-POSITION_SIGNATURE_Y, 
					"Calibri", 
					SIGNATURE_FONT_SIZE, 
					Font.ITALIC);
	}
	
	/**
	 * 
	 * @param text label text
	 * @param x label X position
	 * @param y label Y position
	 * @param fontName name of the font
	 * @param fontSize size of the font
	 */
	private void drawLabel(String text, int x, int y, String fontName, 
							int fontSize, int fontStyle){
		GLabel label = new GLabel(text);
		label.setLocation(x, y);
		
		Font font = new Font(fontName, fontStyle, fontSize);
		
		label.setFont(font);
		
		add(label);
	}
}
